<?php
/**
 * 多进程调度算法
 * 将任务量分配给进程的
 * 一系列算法封装放入此
 * 类中
 */
namespace timer_job\common\helper;

class Dispatch {
    // 简单的任务进程调度分配
    /**
     * 按公约数先平均分配，多余的任务在依次分配
     *
     * @param integer $worker_num 开启的进程数
     * @param array $tasks 任务队列、数组（所有的任务组成的数组）
     * @return array 结果是一个以0开始下标的数组，对应workers的下标可以实现任务与进程对应（任务的下标与进程数组的下标对应）
     */
    public static function dispatchByIndex($worker_num, $tasks) {
        //$in = ceil($task_num/$worker_num);
        $dispatch = [];// 分配的结果数组，该数组以自然下标对应workers进程数组的自然下标，值为对应的分配的任务队列
        $task_num = count($tasks);
        $avg = floor($task_num/$worker_num);
        $remainder = $task_num - $avg * $worker_num;
        switch ($remainder) {
            case 0:
                for ($i=0; $i<$worker_num; $i++) {
                    if ($i == 0) {
                        $dispatch[$i] = array_slice($tasks, 0, $avg);
                    } else {
                        $dispatch[$i] = array_slice($tasks, ($avg)*($i), $avg);
                    }
                }
                break;

            default:
                for ($i=0; $i<$worker_num; $i++) {
                    if ($i == 0) {
                        $dispatch[$i] = array_slice($tasks, 0, $avg+1);
                    } else if($i >= $remainder) {
                        $dispatch[$i] = array_slice($tasks, $remainder*($avg+1)+($i-$remainder)*$avg, $avg);
                    } else {
                        $dispatch[$i] = array_slice($tasks, ($avg+1)*($i), $avg+1);
                    }
                }
                break;
        }
        return $dispatch;
    }
}